package auth

import (
	"fmt"

	"gorm.io/gorm"
)

// Role 角色模型（用于关联查询）
type Role struct {
	ID        uint           `json:"id" gorm:"primaryKey"`
	Code      string         `json:"code"`
	Status    int            `json:"status"`
	DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
}

// Permission 权限模型（用于关联查询）
type Permission struct {
	ID          uint           `json:"id" gorm:"primaryKey"`
	Name        string         `json:"name"`
	Code        string         `json:"code"`
	DisplayName string         `json:"display_name"`
	Path        string         `json:"path"`
	ParentID    uint           `json:"parent_id"`
	Sort        int            `json:"sort"`
	Type        string         `json:"type"`
	Status      int            `json:"status"`
	DeletedAt   gorm.DeletedAt `json:"deleted_at" gorm:"index"`
}

// UserRole 用户角色关联模型
type UserRole struct {
	UserID uint `json:"user_id" gorm:"primaryKey"`
	RoleID uint `json:"role_id" gorm:"primaryKey"`
	Role   Role `json:"role" gorm:"foreignKey:RoleID;references:ID"`
}

// RolePermission 角色权限关联模型
type RolePermission struct {
	RoleID       uint       `json:"role_id" gorm:"primaryKey"`
	PermissionID uint       `json:"permission_id" gorm:"primaryKey"`
	Permission   Permission `json:"permission" gorm:"foreignKey:PermissionID;references:ID"`
}

// Repository 认证数据访问层接口
type Repository interface {
	GetUserByUsername(username string) (*User, error)
	GetUserByEmail(email string) (*User, error)
	GetUserByID(id uint) (*User, error)
	UpdateUser(user *User) error
	UpdateLastLogin(userID uint) error
	GetUserMenus(userID uint) ([]*MenuInfo, error)
	GetUserPermissions(userID uint) ([]string, error)
}

// repository 认证数据访问层实现
type repository struct {
	db *gorm.DB
}

// NewRepository 创建认证数据访问层
func NewRepository(db *gorm.DB) Repository {
	return &repository{
		db: db,
	}
}

// GetUserByUsername 根据用户名获取用户
func (r *repository) GetUserByUsername(username string) (*User, error) {
	var user User
	err := r.db.Where("username = ?", username).First(&user).Error
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// GetUserByEmail 根据邮箱获取用户
func (r *repository) GetUserByEmail(email string) (*User, error) {
	var user User
	err := r.db.Where("email = ?", email).First(&user).Error
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// GetUserByID 根据ID获取用户
func (r *repository) GetUserByID(id uint) (*User, error) {
	var user User
	err := r.db.First(&user, id).Error
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// UpdateUser 更新用户信息
func (r *repository) UpdateUser(user *User) error {
	return r.db.Save(user).Error
}

// UpdateLastLogin 更新最后登录时间
func (r *repository) UpdateLastLogin(userID uint) error {
	return r.db.Model(&User{}).Where("id = ?", userID).Update("last_login", gorm.Expr("NOW()")).Error
}

// GetUserMenus 获取用户菜单
func (r *repository) GetUserMenus(userID uint) ([]*MenuInfo, error) {
	// 定义临时结构体，避免GORM扫描Children字段的问题
	type MenuRow struct {
		ID          uint   `json:"id"`
		Name        string `json:"name"`
		DisplayName string `json:"display_name"`
		Path        string `json:"path"`
		Icon        string `json:"icon"`
		Sort        int    `json:"sort"`
		ParentID    *uint  `json:"parent_id"`
	}

	// 首先检查用户是否是超级管理员
	var userRoles []UserRole
	err := r.db.Preload("Role").Where("user_id = ?", userID).Find(&userRoles).Error
	if err != nil {
		return nil, err
	}

	var isAdmin bool
	for _, ur := range userRoles {
		if ur.Role.Code == "admin" && ur.Role.Status == 1 {
			isAdmin = true
			break
		}
	}

	var permissions []Permission

	// 如果是超级管理员，返回所有菜单
	if isAdmin {
		err = r.db.Where("type = ? AND status = ?", "menu", 1).Order("sort ASC").Find(&permissions).Error
	} else {
		// 普通用户通过角色获取有权限的菜单
		var roleIDs []uint
		for _, ur := range userRoles {
			if ur.Role.Status == 1 {
				roleIDs = append(roleIDs, ur.RoleID)
			}
		}

		if len(roleIDs) > 0 {
			var rolePermissions []RolePermission
			err = r.db.Preload("Permission").Where("role_id IN ?", roleIDs).Find(&rolePermissions).Error
			if err != nil {
				return nil, err
			}

			// 提取菜单权限
			permissionMap := make(map[uint]Permission)
			for _, rp := range rolePermissions {
				if rp.Permission.Type == "menu" && rp.Permission.Status == 1 {
					permissionMap[rp.Permission.ID] = rp.Permission
				}
			}

			// 转换为切片
			for _, perm := range permissionMap {
				permissions = append(permissions, perm)
			}
		}
	}

	// 转换为MenuRow格式
	var menuRows []MenuRow
	for _, perm := range permissions {
		var parentID *uint
		if perm.ParentID != 0 {
			parentID = &perm.ParentID
		}

		menuRows = append(menuRows, MenuRow{
			ID:          perm.ID,
			Name:        perm.Name,
			DisplayName: perm.DisplayName,
			Path:        perm.Path,
			Icon:        "", // 如果Permission模型中有Icon字段，可以添加
			Sort:        perm.Sort,
			ParentID:    parentID,
		})
	}

	if err != nil {
		return nil, err
	}

	// 添加调试日志
	fmt.Printf("查询到的菜单行数: %d\n", len(menuRows))
	for i, row := range menuRows {
		parentIDStr := "nil"
		if row.ParentID != nil {
			parentIDStr = fmt.Sprintf("%d", *row.ParentID)
		}
		title := row.DisplayName
		if title == "" {
			title = row.Name
		}
		fmt.Printf("菜单 %d: ID=%d, Name=%s, DisplayName=%s, Title=%s, Path=%s, ParentID=%s\n", i, row.ID, row.Name, row.DisplayName, title, row.Path, parentIDStr)
	}

	// 转换为MenuInfo结构体
	var menus []*MenuInfo
	for _, row := range menuRows {
		title := row.DisplayName
		if title == "" {
			title = row.Name
		}
		menu := &MenuInfo{
			ID:       row.ID,
			Name:     row.Name,
			Title:    title,
			Path:     row.Path,
			Icon:     row.Icon,
			Sort:     row.Sort,
			ParentID: row.ParentID,
			Children: nil, // 初始化为nil，构建树时会设置
		}
		menus = append(menus, menu)
	}

	fmt.Printf("转换后的菜单数量: %d\n", len(menus))

	// 构建菜单树
	result := buildMenuTree(menus)
	fmt.Printf("构建树后的根菜单数量: %d\n", len(result))

	return result, nil
}

// GetUserPermissions 获取用户权限
func (r *repository) GetUserPermissions(userID uint) ([]string, error) {
	var permissions []string

	// 检查用户是否是超级管理员
	var userRoles []UserRole
	err := r.db.Preload("Role").Where("user_id = ?", userID).Find(&userRoles).Error
	if err != nil {
		return nil, err
	}

	var isAdmin bool
	for _, ur := range userRoles {
		if ur.Role.Code == "admin" && ur.Role.Status == 1 {
			isAdmin = true
			break
		}
	}

	// 如果是超级管理员，返回所有权限
	if isAdmin {
		var allPermissions []Permission
		err := r.db.Where("status = ?", 1).Find(&allPermissions).Error
		if err != nil {
			return nil, err
		}

		for _, perm := range allPermissions {
			permissions = append(permissions, perm.Name)
		}
		return permissions, nil
	}

	// 普通用户通过角色获取权限
	var roleIDs []uint
	for _, ur := range userRoles {
		if ur.Role.Status == 1 {
			roleIDs = append(roleIDs, ur.RoleID)
		}
	}

	if len(roleIDs) > 0 {
		var rolePermissions []RolePermission
		err = r.db.Preload("Permission").Where("role_id IN ?", roleIDs).Find(&rolePermissions).Error
		if err != nil {
			return nil, err
		}

		// 使用map去重
		permissionMap := make(map[string]bool)
		for _, rp := range rolePermissions {
			if rp.Permission.Status == 1 {
				permissionMap[rp.Permission.Name] = true
			}
		}

		// 转换为切片
		for name := range permissionMap {
			permissions = append(permissions, name)
		}
	}

	return permissions, nil
}

// buildMenuTree 构建菜单树
func buildMenuTree(menus []*MenuInfo) []*MenuInfo {
	fmt.Printf("开始构建菜单树，输入菜单数量: %d\n", len(menus))

	menuMap := make(map[uint]*MenuInfo)
	var rootMenus []*MenuInfo

	// 创建菜单映射
	for _, menu := range menus {
		menuMap[menu.ID] = menu
		fmt.Printf("添加到映射: ID=%d, Name=%s, ParentID=%v\n", menu.ID, menu.Name, menu.ParentID)
	}

	// 构建树结构
	for _, menu := range menus {
		if menu.ParentID == nil {
			fmt.Printf("找到根菜单: ID=%d, Name=%s\n", menu.ID, menu.Name)
			rootMenus = append(rootMenus, menu)
		} else {
			fmt.Printf("处理子菜单: ID=%d, Name=%s, ParentID=%d\n", menu.ID, menu.Name, *menu.ParentID)
			if parent, exists := menuMap[*menu.ParentID]; exists {
				if parent.Children == nil {
					parent.Children = make([]*MenuInfo, 0)
				}
				parent.Children = append(parent.Children, menu)
				fmt.Printf("成功添加子菜单到父菜单: %s -> %s\n", menu.Name, parent.Name)
			} else {
				fmt.Printf("警告：找不到父菜单 ID=%d\n", *menu.ParentID)
			}
		}
	}

	fmt.Printf("构建完成，根菜单数量: %d\n", len(rootMenus))
	return rootMenus
}
